
module FM_Demodulator
#(
    parameter WIDTH=10,
    parameter MAXINTERVAL_WIDTH = 8,
    parameter MAXINTERVAL = 64

)
(
    input wire signed [WIDTH-1:0] i_FM_Signal,
    input wire [MAXINTERVAL_WIDTH-1:0] i_DiffInterval,
    input wire [MAXINTERVAL_WIDTH-1:0] i_EnveInterval,
    input wire i_clk,
    input wire i_rst,
    output wire signed [WIDTH-1:0] o_Baseband
);

//Generate Shift Register
wire signed [WIDTH-1:0] Shift_Reg [MAXINTERVAL-1:0];
genvar i;
generate
for( i=0 ; i<MAXINTERVAL ; i=i+1 )begin: shreg_first_stage
    if(i==0)begin: fir_first_input_reg_del
        Shift_Reg_FM  
        #(  
            .WIDTH    (WIDTH)
        )diff_reg(
            .i_clk    (i_clk),
            .i_rst    (i_rst),
            .i_regin     (i_FM_Signal),
            .o_regout    (Shift_Reg[i])
        );
    end
    else begin: shreg_mid_stage
        Shift_Reg_FM   
        #(  
            .WIDTH    (WIDTH)
        )diff_reg(
            .i_clk (i_clk),
            .i_rst (i_rst),
            .i_regin  (Shift_Reg[i-1]),
            .o_regout (Shift_Reg[i])
        );
    end
end
endgenerate

//Differentiator
wire signed [WIDTH-1:0] diff;
assign diff=i_FM_Signal-Shift_Reg[i_DiffInterval-1];

//Envelope_Detector
Envelope_Detector_Digital 
#(
    .WIDTH(WIDTH),
    .MAXINTERVAL(MAXINTERVAL),
    .MAXINTERVAL_WIDTH(MAXINTERVAL_WIDTH)
)
ED_FM
(
    .i_SignalInput(diff),
    .i_Interval(i_EnveInterval),
    .i_clk(i_clk),
    .i_rst(i_rst),
    .o_Envelope(o_Baseband)
);


endmodule

module Shift_Reg_FM
#(
    parameter WIDTH = 10
)
(
    input wire [WIDTH-1:0] i_regin,
    input wire i_clk,
    input wire i_rst,
    output reg [WIDTH-1:0] o_regout
);

always@(posedge i_clk or posedge i_rst) begin
    if(i_rst) begin
        o_regout<='b0;
    end
    else begin
        o_regout<=i_regin;
    end
end

endmodule
